#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>
#include "metainfo.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    trackerClient(NULL), connectionsManager(NULL)
{
    ui->setupUi(this);
    QSettings settings("P2PaON", "TorrentClientProject");
    QString lastTorrentFile = settings.value("last_file").toString();
    ui->lineEditTorrentFileName->setText(lastTorrentFile);
    bool result1 = connect(ui->buttonOpenTorrentFile, SIGNAL(clicked()), this, SLOT(showOpenTorrentFileDialog()));
    bool result2 = connect(ui->buttonStartDownloading, SIGNAL(clicked()), this, SLOT(startDownloadingFile()));
    Q_ASSERT(result1 && result2);
    connectionsManager = new ConnectionsManager(this);


}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}
void MainWindow::showOpenTorrentFileDialog()
{
    QString torrentFilePath;
    //get directory containing last file opened
    QString lastFilePath = ui->lineEditTorrentFileName->text();
    if (lastFilePath.isEmpty())
    {
        lastFilePath = QString::null;
    }
    else
    {
        QString slashEscaped = QRegExp::escape("/");
        QRegExp rxFileNameInPath(slashEscaped + "{1}[^" + slashEscaped + "]*$");
        lastFilePath.replace(rxFileNameInPath, "");
    }
    torrentFilePath = QFileDialog::getOpenFileName(
            this,
            "Choose a file to open",
            lastFilePath,
            tr("Torrent file: (*.torrent);; All files(*)"));

    if(torrentFilePath.isEmpty())
    {
        return;
    }


        ui->lineEditTorrentFileName->setText( torrentFilePath );    
}

//opens .torrent file and parses it
void MainWindow::openTorrentFile(const QString& fileName)
{
    QFile torrentFile(fileName);
    if (!torrentFile.open(QFile::ReadOnly))
        {
        showErrorMessage("Error: Can not open file " + fileName);
        return;
        }

    QByteArray byteStream = torrentFile.readAll();
    MetaInfo metaInfoReader;
    if (!metaInfoReader.parse(byteStream))
    {
        showErrorMessage("Error: Invalid .torrent file " + fileName );
        return;
    }
    if (metaInfoReader.fileForm() == MetaInfo::MultiFileForm)
    {
        showErrorMessage("Error: multi-file .torrent files are not supported by this client");
        return;

    }
    //TODO delete TrackerClient??
    delete trackerClient;
    delete connectionsManager;
    trackerClient = new TrackerRequest(metaInfoReader, this);
    connectionsManager = new ConnectionsManager(this);
    disconnect( trackerClient, SIGNAL(requestCompleted(QString)), this, SLOT(trackerRequestCompleted(QString)) );
    disconnect(trackerClient, SIGNAL(requestError(QString)), this, SLOT(trackerRequestError(QString)) );
    disconnect(trackerClient, SIGNAL(peersListReceived(QList<TorrentPeerData>&)),
               connectionsManager, SLOT(peersDataReceived(QList<TorrentPeerData>&)));
    bool result1 = connect(trackerClient, SIGNAL(requestCompleted(QString)),
                 this, SLOT(trackerRequestCompleted(QString)));
    bool result2 = connect(trackerClient, SIGNAL(requestError(QString)), this, SLOT(trackerRequestError(QString)) );
    bool result3 = connect(trackerClient, SIGNAL(peersListReceived(QList<TorrentPeerData>&)),
               connectionsManager, SLOT(peersDataReceived(QList<TorrentPeerData>&)));
    result3 = connect(connectionsManager, SIGNAL(error(QString)), this, SLOT(error(QString)));
    Q_ASSERT(result3);
    result3 = connect(connectionsManager, SIGNAL(downloadCompleted()), this, SLOT(downloadCompleted()));
    Q_ASSERT(result3);
    result3 = connect(connectionsManager, SIGNAL(downloadsTableChanged(QMap<TorrentConnection*,QPair<int,int> >*)),
                                          this, SLOT(updateDownloadsTable(QMap<TorrentConnection*,QPair<int,int> >*)));
    result3 = connect(connectionsManager, SIGNAL(transferRateUpdated(double)),
                      this, SLOT(updateTransferRate(double)));
    Q_ASSERT(result3);
    if (! (result1 && result2 && result3) )
        Q_ASSERT("signal - slot connection error");

    //remember file name
     QSettings settings("P2PaON", "TorrentClientProject");
     settings.setValue("last_file", fileName);

     //clear ui if downloading next file
     while(ui->tableDownloads->rowCount())
     {
         ui->tableDownloads->removeRow(ui->tableDownloads->rowCount() -1 );
     }
     ui->logTextBrowser->clear();
     //send request to tracker
     Q_ASSERT(trackerClient);
     trackerClient->start();


}
void MainWindow::showErrorMessage(const QString& reason)
{
    QMessageBox errorMessage(this);
    errorMessage.setText(reason);
    errorMessage.exec();
}
void MainWindow::trackerRequestCompleted(QString result)
{
    QString message;
    message = "Tracker response: " + result;
    qDebug() << message;
    QString torrentFilePath = ui->lineEditTorrentFileName->text();
    QString dirPath = QDir::toNativeSeparators(QFileInfo(torrentFilePath).absoluteDir().absolutePath());
    dirToDownload = QDir(dirPath);
    qDebug() << "file will be saved in directory: " << dirToDownload.absolutePath();
    connectionsManager->startFile(trackerClient->getTorrentInfo(),
                                  trackerClient->getInfoHash(),
                                  dirToDownload);
    ui->buttonStartDownloading->setEnabled(false);
}
void MainWindow::trackerRequestError(QString reason)
{
    showErrorMessage(reason);
}
void MainWindow::error(QString message)
{
    showErrorMessage(message);
}
void MainWindow::downloadCompleted()
{
    QMessageBox* msg = new QMessageBox(this);
    msg->setText("File succesfully downloaded !");
    msg->exec();
    ui->buttonStartDownloading->setEnabled(true);
    log("\nDownloading finished!\n");
    //close();
}

void MainWindow::startDownloadingFile()
{    
    openTorrentFile(ui->lineEditTorrentFileName->text());

}
void MainWindow::log(const QString &text)
{
    ui->logTextBrowser->append(text);
    ui->logTextBrowser->append("");
}
void MainWindow::updateDownloadsTable(QMap<TorrentConnection *, QPair<int, int> > * downloadsMap)
{
   int rows = ui->tableDownloads->rowCount();
   ui->tableDownloads->clearContents();
   while(ui->tableDownloads->rowCount())
   {
       ui->tableDownloads->removeRow(ui->tableDownloads->rowCount() - 1);
   }
   rows = ui->tableDownloads->rowCount();
    foreach(TorrentConnection* peer, downloadsMap->keys())
   {
        QPair<int, int> pieceBlock = downloadsMap->value(peer);
        rows = ui->tableDownloads->rowCount();
        ui->tableDownloads->insertRow(ui->tableDownloads->rowCount());

        ui->tableDownloads->setItem(ui->tableDownloads->rowCount() - 1, 0,
                                    new QTableWidgetItem(
                                            peer->getPeerData().ipAddress.toString()));
        ui->tableDownloads->setItem(ui->tableDownloads->rowCount() - 1, 1,
                                    new QTableWidgetItem(QString::number(pieceBlock.first)));
        ui->tableDownloads->setItem(ui->tableDownloads->rowCount() - 1, 2,
                                    new QTableWidgetItem(QString::number(pieceBlock.second)));
        rows = ui->tableDownloads->rowCount();
        ui->tableDownloads->update();
   }
    update();
}
void MainWindow::updateTransferRate(double transferRate)
{
    ui->statusBar->showMessage("Transfer rate: "
                               + QString::number(transferRate, 'f', 1) + " kB/s");
}
